﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of RinexFileReader.                                       **
**                                                                              **
**  RinexFileReader is free software: you can redistribute it and/or modify     **
**  it under the terms of the GNU General Public License as published by        **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  RinexFileReader is distributed in the hope that it will be useful,          **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU General Public License for more details.                                **
**                                                                              **
**  You should have received a copy of the GNU General Public License           **
**  along with RinexFileReader. If not, see <https://www.gnu.org/licenses/>.    **
**********************************************************************************/
#pragma once

#include <optional>
#include <string>
#include <variant>
#include <vector>

namespace Rinex
{
enum class SatelliteSystem
{
    GPS,
    GLONASS,
    Galileo,
    QZSS,
    BDS,
    NavIC,
    SBASPayload,
    Mixed
};

enum class SystemTimeIdentifier
{
    GPS,
    GLONASS,
    Galileo,
    QZSS,
    BDS,
    NavIC
};

enum class CorrectionType
{
    GAL,  // Galileo ai0 - ai2
    GPSA, // GPS alpha0 - alpha3
    GPSB, // GPS beta0 - beta3
    QZSA, // QZS alpha0 - alpha3
    QZSB, // QZS beta0 - beta3
    BDSA, // BDS alpha0 - alpha3
    BDSB, // BDS beta0 - beta3
    IRNA, // NavIC/IRNSS alpha0 - alpha3
    IRNB  // NavIC/IRNSS beta0 - beta3
};

enum class TimeSystemCorrType
{
    GPUT, // GPS - UTC (a0, a1)
    GLUT, // GLO - UTC (a0= -TauC, a1=zero)
    GAUT, // GAL - UTC ( a0, a1)
    BDUT, // BDS - UTC (a0=A0UTC, a1=A1UTC )
    QZUT, // QZS - UTC (a0, a1)
    IRUT, // IRN - UTC (a0=A0UTC, a1=A1UTC )
    SBUT, // SBAS - UTC (a0, a1)
    GLGP, // GLO - GPS (a0=-TauGPS, a1=zero)
    GAGP, // GAL - GPS (See **Note Below) (a0 = A0G, a1 = A1G for GAL INAV/FNAV; a0 = –A0GGTO, a1 = –A1 GGTO for GPS CNAV)
    QZGP, // QZGP = QZS - GPS (a0, a1)
    IRGP  // IRGP =IRN - GPS (a0=A0, a1=A1 )
};

enum class ObservationType
{
    Pressure,
    DryTemperature,
    RelativeHumidity,
    WetZenithPathDelay,
    DryComponentOfZenPathDelay,
    TotalZenithPathDelay,
    WindAzimuth,
    WindSpeed,
    RainIncrement,
    HailIndicator
};

struct DateTime
{
    int year;
    int month;
    int day;
    int hour;
    int minute;
    int second;
    int msec;
};

struct PhaseCenter
{
    SatelliteSystem satelliteSystem;
    std::string observationCode;
    std::tuple<double, double, double> northEastUpOrXYZ;
};

struct SysObsTypes
{
    SatelliteSystem satelliteSystem;
    std::vector<std::string> types;
};

struct TimeOfObs
{
    DateTime time;
    SystemTimeIdentifier systemTime;
};

struct GLONASSSlotFreq
{
    char systemCode;
    int slot_; // avoid Qt Moc
    int frequencyNumber;
};

struct LeapSeconds
{
    std::optional<int> currentNumber;
    std::optional<int> deltaTLSF;
    std::optional<int> wnLSF;
    std::optional<int> respectiveDayNumber;
    SystemTimeIdentifier systemTimeIdentifier;
};

struct PrnOfObs
{
    SatelliteSystem satelliteSystem;
    int id;
    std::vector<std::optional<int>> records;
};

struct ObsRecords
{
    SatelliteSystem satelliteSystem;
    int id;
    struct Record
    {
        double record;
        std::optional<int> lli;
        std::optional<int> ssi;
    };
    std::vector<std::optional<Record>> records;
};

struct ObsData
{
    DateTime epoch;
    int epochFlag;
    int numberOfSatellites;
    std::optional<double> receiverClockOffsetCorrection;
    std::vector<ObsRecords> records;
};

struct IonosphericCorr
{
    CorrectionType correctionType;
    std::vector<double> parameters;
    std::optional<char> timeMark; // A=BDT 00h-01h;B=BDT 01h-02h;...;X= BDT 23h-24h.
    std::optional<int> svID;
};

struct TimeSystemCorr
{
    TimeSystemCorrType type;
    double a0;
    double a1;
    int t;
    int w;
    std::optional<std::string> satelliteID;
    std::optional<int> utcIdentifier;
};

struct NMData
{
    SatelliteSystem satelliteSystem;
    int id;
    DateTime epoch;
    std::vector<std::optional<double>> datas;
};

struct SensorModTypeAcc
{
    std::string model;
    std::string type;
    double accuracy;
    ObservationType obsType;
};

struct SensorPosXYZH
{
    double x;
    double y;
    double z;
    double h;
    ObservationType type;
};

struct MetData
{
    DateTime dateTime;
    std::vector<double> datas;
};
} // namespace Rinex